/*
 * @Author: “ygnnli” “1585923072@qq.com”
 * @Date: 2024-08-09 18:45:12
 * @LastEditors: “ygnnli” “1585923072@qq.com”
 * @LastEditTime: 2024-08-10 10:10:23
 * @FilePath: /83/Reactor/IOService.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AEma
 */
#pragma once

#include <iostream>
#include "Connection.hpp"
#include "Log.hpp"
#include <sys/types.h>
#include <sys/socket.h>

// 处理连接的读写事件
class HandlerConnection
{
public:
    HandlerConnection(func_t func) : _func(func)
    {
    }

    void HandlerRecv(Connection *conn)
    {
        errno = 0;//可能是上次的errno
        LOG(DEBUG, "HandlertRecv fd : %d\n", conn->Sockfd());
        while (true)
        {
            char buffer[1024];
            ssize_t n = ::recv(conn->Sockfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = '\0';
                conn->AppendInBuffer(buffer);
            }
            else
            {
                // EAGAIN 缓冲区为空或者缓冲区已满   EWOULDBLOCK 非阻塞模式下，没有数据可读
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR) // 被信号中断
                {
                    continue;
                }
                else
                {
                    conn->_excepter(conn); // 发生异常，调用异常处理函数
                    return;
                }
            }
        }
        _func(conn); // 处理完数据后，调用回调函数
    }

    void HandlerSend(Connection *conn)
    {
        while (true)
        {
            ssize_t n = ::send(conn->Sockfd(), conn->Outbuffer().c_str(), conn->Outbuffer().size(), 0); // 发送数据
            if (n > 0)
            {
                conn->OutbufferRemove(n); // 发送成功，从缓冲区中移除已发送的数据
                if (conn->OutbufferEmpty())
                    break; // 缓冲区为空，则退出循环
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                if (errno == EWOULDBLOCK || errno == EAGAIN) // EAGAIN 缓冲区为空或者缓冲区已满   EWOULDBLOCK 非阻塞模式下，读或写失败
                {
                    break;
                }
                else if (errno == EINTR) // 被信号中断
                {
                    continue;
                }
                else
                {
                    conn->_excepter(conn); // 发生异常，调用异常处理函数
                    return;
                }
            }

            // 一定是缓冲区写满，还有数据没有发送出去
            if (!conn->OutbufferEmpty())
            {
                conn->_R->EnableReadWrite(conn->Sockfd(), true, true); // 开启对读事件关心
            }
            else
            {
                conn->_R->EnableReadWrite(conn->Sockfd(), true, false); // 关闭对写事件关心
            }
        }
    }

    void HandlerExcpet(Connection *conn)
    {
        errno = 0;
        LOG(DEBUG, "client quit : %d\n", conn->Sockfd()); // 客户端退出
        // 1. 去掉epoll对该文件fd的关心
        // 2. 服务器端也要关闭sockfd
        // 3. 释放connection
        conn->_R->RemoveConnection(conn->Sockfd());

    }

private:
    func_t _func; // 任务回调函数
};